package puzzle.util;

import java.io.*;
import java.net.*;
import java.io.*;
import java.util.zip.*;
import org.dom4j.*;
import org.dom4j.io.*;
import puzzle.core.*;
import puzzle.core.tiles.*;
import org.newdawn.slick.loading.*;
import org.newdawn.slick.util.*;
import java.util.*;

public class ResourceManager extends ResourceLoader {
  
  //The resource bundle (properties file)
  private static ResourceBundle bundle = 
                    ResourceManager.createResourceBundle("data/bpuz.properties");
  
  public static ResourceBundle createResourceBundle(String ref) {
    try {
      InputStream in = getResourceAsStream(ref);
      return new PropertyResourceBundle(in);
    }
    catch (Exception e) {
      Log.error("Can't find property file: "+ref, e);
      return null;
    }
  }
  
  private static boolean deferred = false;
  
  public static void setDeferredLoading(boolean b) {
    LoadingList.setDeferredLoading(b);
    deferred = b;
  }
  
  public static boolean isDeferredLoading() {
    return deferred;
  }
  
  public static String getString(String key, String def) {
    if (key==null)
      return def;
    String ret = null;
    try {
      ret = (bundle!=null) ? bundle.getString(key) : def; 
    } catch (MissingResourceException e) {
      ret = def;
    }
    if (ret==null)
      Log.warn("Key not found: "+key);
    return (ret!=null) ? ret.trim() : def.trim();
  }
  
  public static URL getResource(String ref) {
    URL url = ResourceLoader.class.getClassLoader().getResource(ref);
    
    if (url == null) {
      File file = new File(ref);
      try {
        if (System.getProperty("jnlp.slick.webstart", "false").equals("false")) {
          url = file.toURI().toURL();
        } else {
          Log.error("Resource not found: "+ref);
          throw new RuntimeException("Resource not found: "+ref);
        }
      }
      catch (IOException e) {
        Log.error("Resource not found: "+ref);
        throw new RuntimeException("Resource not found: "+ref);
      }
    }
    return url; 
  }
  
  public static LoadingList getLoadingList() {
    return LoadingList.get();
  }
  
  /** 
   * A nice utility method to find the relative path between two files.
   * I did not write this.
   * <p> 
   * http://forum.java.sun.com/thread.jspa?threadID=584546&tstart=30
   *
   * @author rioriorio945
   */
  public static String getRelativePath(File file, File relativeTo) throws IOException {
    file       = new File(file + File.separator + "89243jmsjigs45u9w43545lkhj7").getParentFile();
    relativeTo = new File(relativeTo + File.separator + "984mvcxbsfgqoykj30487df556").getParentFile();

    File      origFile            = file;
    File      origRelativeTo      = relativeTo;
    ArrayList<File> filePathStack       = new ArrayList<File>();
    ArrayList<File> relativeToPathStack = new ArrayList<File>();

    //build the path stack info to compare it afterwards
    file = file.getCanonicalFile();

    while (file != null) {
        filePathStack.add(0, file);
        file = file.getParentFile();
    }
    relativeTo = relativeTo.getCanonicalFile();

    while (relativeTo != null) {
        relativeToPathStack.add(0, relativeTo);
        relativeTo = relativeTo.getParentFile();
    }
    
    //compare as long it goes
    int count = 0;

    file       = (File) filePathStack.get(count);
    relativeTo = (File) relativeToPathStack.get(count);

    while ((count < filePathStack.size() - 1) && (count < relativeToPathStack.size() - 1)
            && file.equals(relativeTo)) {
        count++;
        file       = (File) filePathStack.get(count);
        relativeTo = (File) relativeToPathStack.get(count);
    }

    if (file.equals(relativeTo)) {
        count++;
    }

    //up as far as necessary
    StringBuffer relString = new StringBuffer();

    for (int i = count; i < relativeToPathStack.size(); i++) {
        relString.append(".." + File.separator);
    }

    //now back down to the file
    for (int i = count; i < filePathStack.size() - 1; i++) {
      relString.append(((File) filePathStack.get(i)).getName() + File.separator);
    }
    relString.append(((File) filePathStack.get(filePathStack.size() - 1)).getName());

    //just to test
    File relFile = new File(origRelativeTo.getAbsolutePath() + File.separator + relString.toString());
    if (!relFile.getCanonicalFile().equals(origFile.getCanonicalFile())) {
      throw new IOException("Failed to find relative path.");
    }
    return relString.toString();
  }
}


